package com.virtualperson.util;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Properties;

@Slf4j
@Component
public class ServerConnectionUtil {

    @Value("${app.storage.server.host}")
    private String serverHost;

    @Value("${app.storage.server.port:22}")
    private int serverPort;

    @Value("${app.storage.server.username}")
    private String username;

    @Value("${app.storage.server.password}")
    private String password;

    @Value("${app.storage.server.private-key-path:}")
    private String privateKeyPath;

    @Value("${app.storage.server.connection-timeout:30000}")
    private int connectionTimeout;

    /**
     * 测试服务器连接
     * @return 连接测试结果
     */
    public ConnectionTestResult testConnection() {
        Session session = null;
        ChannelSftp channelSftp = null;
        
        try {
            log.info("开始测试服务器连接: {}:{}", serverHost, serverPort);
            
            // 创建JSch对象
            JSch jsch = new JSch();
            
            // 设置认证方式
            if (privateKeyPath != null && !privateKeyPath.trim().isEmpty()) {
                jsch.addIdentity(privateKeyPath);
                log.info("使用私钥认证");
            } else {
                log.info("使用密码认证");
            }
            
            // 创建会话
            session = jsch.getSession(username, serverHost, serverPort);
            
            // 设置连接参数
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setTimeout(connectionTimeout);
            
            // 如果使用密码认证，设置密码
            if (privateKeyPath == null || privateKeyPath.trim().isEmpty()) {
                session.setPassword(password);
            }
            
            // 连接服务器
            session.connect();
            log.info("SSH连接成功");
            
            // 测试SFTP通道
            Channel channel = session.openChannel("sftp");
            channel.connect(connectionTimeout);
            channelSftp = (ChannelSftp) channel;
            log.info("SFTP通道测试成功");
            
            return new ConnectionTestResult(true, "连接测试成功");
            
        } catch (Exception e) {
            log.error("服务器连接测试失败", e);
            return new ConnectionTestResult(false, "连接测试失败: " + e.getMessage());
        } finally {
            // 关闭连接
            if (channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 检查远程目录是否存在
     * @param remotePath 远程路径
     * @return 检查结果
     */
    public DirectoryCheckResult checkRemoteDirectory(String remotePath) {
        Session session = null;
        ChannelSftp channelSftp = null;
        
        try {
            // 创建JSch对象
            JSch jsch = new JSch();
            
            // 设置认证方式
            if (privateKeyPath != null && !privateKeyPath.trim().isEmpty()) {
                jsch.addIdentity(privateKeyPath);
            }
            
            // 创建会话
            session = jsch.getSession(username, serverHost, serverPort);
            
            // 设置连接参数
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setTimeout(connectionTimeout);
            
            // 如果使用密码认证，设置密码
            if (privateKeyPath == null || privateKeyPath.trim().isEmpty()) {
                session.setPassword(password);
            }
            
            // 连接服务器
            session.connect();
            
            // 打开SFTP通道
            Channel channel = session.openChannel("sftp");
            channel.connect(connectionTimeout);
            channelSftp = (ChannelSftp) channel;
            
            // 检查目录是否存在
            try {
                channelSftp.cd(remotePath);
                return new DirectoryCheckResult(true, "目录存在且可访问", true);
            } catch (SftpException e) {
                if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
                    return new DirectoryCheckResult(true, "目录不存在", false);
                } else {
                    return new DirectoryCheckResult(false, "检查目录失败: " + e.getMessage(), false);
                }
            }
            
        } catch (Exception e) {
            log.error("检查远程目录失败: {}", remotePath, e);
            return new DirectoryCheckResult(false, "检查目录失败: " + e.getMessage(), false);
        } finally {
            // 关闭连接
            if (channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 连接测试结果
     */
    public static class ConnectionTestResult {
        private boolean success;
        private String message;

        public ConnectionTestResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
    }

    /**
     * 目录检查结果
     */
    public static class DirectoryCheckResult {
        private boolean connectionSuccess;
        private String message;
        private boolean directoryExists;

        public DirectoryCheckResult(boolean connectionSuccess, String message, boolean directoryExists) {
            this.connectionSuccess = connectionSuccess;
            this.message = message;
            this.directoryExists = directoryExists;
        }

        public boolean isConnectionSuccess() { return connectionSuccess; }
        public void setConnectionSuccess(boolean connectionSuccess) { this.connectionSuccess = connectionSuccess; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public boolean isDirectoryExists() { return directoryExists; }
        public void setDirectoryExists(boolean directoryExists) { this.directoryExists = directoryExists; }
    }
} 